﻿/// <reference path="jquery-1.4.2.js" />





///登陆扣费计时 baseTimeUnit 基本计时单位(分钟) feeType 0 套餐扣费 1 标准资费
//count  与tempCount比较时间，如果超过一个基本扣费单位就加入扣费列表，加入之后tempCount 赋值为count
//重新获取资费后tempCount 也赋值为count
var LogOnDeductionTimeFee = function (baseTimeUnit, feeType, deductionTimeUrl) {
    var hRemainCount = $('#hidOnlineLeftTime').val();
    var startTime;
    var iClock;
    var tempTime = 0;
    var remainTotalCount = parseInt(hRemainCount); //剩余时长
    var tempCount = 0; //用来计算是否加入扣费列表
    var pauseFlag = true; //z暂停计时器
    var interval = 5000; //时间间隔
    var tMSec;
    var firstDeduct = true;


    var loginClock = function () {

        var endTime = (new Date).getTime();
        var count = endTime - startTime; //记录总用时
        tMSec = Date.MillisecondToDate(count);
        var href = deductionTimeUrl + "&isEnd=false";
        var minutes = parseInt(count / 60000);
        remainTotalCount = hRemainCount - minutes;
        setShowText(count); //显示计时信息
        if (hRemainCount * 60000 - count <= 20000)//如果小于10秒的时候执行扣费，重新获取费用
        {
            pauseFlag = false; //暂停计时
            href = deductionTimeUrl + "&isEnd=true";
            $.getJSON(href, function (data) {
                if (data.success) {
                    if (data.data.FeeTypes.length > 0) {
                        //按标准资费重新设置剩余时间
                        //baseTimeUnit = data.data.BaseCharge; //重置基本计时单位;
                        remainTotalCount = hRemainCount = data.data.RemainCount;
                        $('#hidOnlineLeftTime').val(remainTotalCount);
                        startTime = (new Date).getTime();
                        tempCount = 0;
                        feeType = data.data.FeeType;
                        firstDeduct = true;
                        if (data.data.RemainCount <= 0)//是标准资费，转到费用选择界面
                        {
                            window.parent.location = "/Fee/Home/FeeTypeSelect";
                            clearTimeout(iClock);
                        }
                        else {
                            pauseFlag = true;
                            loginClock();
                        }
                    }
                }

            }, 'json');

        }
        //先加扣费列表
        if (remainTotalCount > 0 && pauseFlag) {
            if (firstDeduct == true) {
                //执行加入列表
                $.getJSON(href, function (data) {

                });
            }
            firstDeduct = false;
        }

        //如果当前时间-临时时间 >=基本扣费时间,加入扣费列表
        if (count - tempCount >= baseTimeUnit * 60000) {//超过基本计时单位加入列表 
            //执行加入列表
            $.getJSON(href, function (data) {

            });
            tempCount = count;
        }

        if (pauseFlag)
            iClock = window.setTimeout(loginClock, interval);
        if (minutes > 0) {//*分钟倒计时  
            if (remainTotalCount <= 0) {//强制跳转
                goToSelectPage();
            }
        }

    };

    function setShowText(count) {
        var min = parseInt((hRemainCount * 60000 - count) / 60000) > 0 ? parseInt((hRemainCount * 60000 - count) / 60000) : 0;
        var second = parseInt(((hRemainCount * 60000 - count) % 60000) / 1000) > 0 ? parseInt(((hRemainCount * 60000 - count) % 60000) / 1000) : 0;
        var showText = min + "分" + second + "秒";
        if (remainTotalCount <= 5) {
            $('#OnlineLeftTime').html("<font color='#FF0000'> 剩余时长:" + showText + "</font>");
        } else {
            $('#OnlineLeftTime').html("剩余时长:" + showText + "");
        }
    };

    window.onload = function () {
        startTime = tempTime = (new Date).getTime();
        loginClock();
    };



    //调转到选择费用页面
    function goToSelectPage() {
        clearTimeout(iClock);
        var href = deductionTimeUrl + "&isEnd=true";
        $.getJSON(href, function (data) {
            window.parent.location = "/Fee/Home/FeeTypeSelect";
        });
    }

};



//替换myUrl中的同名参数值 追加
function RegularUrl(url, key, value) {
    if (typeof (value) == 'undefined' || value == null)//如果值为空不设置
        return url;
    var fragPos = url.lastIndexOf("#");
    var fragment = "";
    if (fragPos > -1) {
        fragment = url.substring(fragPos);
        url = url.substring(0, fragPos);
    }
    var querystart = url.indexOf("?");
    if (querystart < 0) {
        url += "?" + key + "=" + value;
    }
    else if (querystart == url.length - 1) {
        url += key + "=" + value;
    }
    else {
        var Re = new RegExp(key + "=[^\\s&#]*", "gi");
        if (Re.test(url))
            url = url.replace(Re, key + "=" + value);
        else
            url += "&" + key + "=" + value;
    }
    return url + fragment;
};




function onCardData(cardNum, macs) {
    $(window).trigger("receivecard", [cardNum, macs]);
}

$(function () {
    var alertEle;
    //提交数组格式设置
    $.ajaxSettings.traditional = true;
    $.ajaxSettings.cache = false;
    //ajax请求登录重定向
    $(window).ajaxSend(function (evt, request, settings) {
        if (!settings.dataType || settings.dataType == 'json') {
            var oldfunc = settings.success;
            settings.success = function (data) {
                if (data && data.data && data.data._url)
                    window.location = data.data._url;
                else
                    oldfunc(data);
            };

        }
    });

    $('#exportSearch').click(function () {
        var self = $(this);
        var url = this.href + '?' + $.param(self.parents('.TableRegion').find(':input').SerializeElements());
        window.open(url);
        return false;
    });


    $(':input').focus(function () {
        $(this).addClass('focus');
    }).blur(function () {
        $(this).removeClass('focus');
    });
    $('dl.dlf,dl.dlf>dt,dl.dlf>dd').addClass('inlineBlock inline');

    $('ul.ul-datalist>li>dl>dt,ul.ul-datalist>li>dl>dd').addClass('inlineBlock inline');

    $('dl.dlf.hidden').hide();

    $('input:submit:not(:has(".login"))').addClass('normal');

    //时间设置
    $.datepicker.setDefaults({ autoSize: true, dateFormat: "yyyy-MM-dd", changeMonth: true, changeYear: true, yearRange: 'c-100:c+10' });
    $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
    $.fn.getContraryDate = function () {
        var isMin = false;
        var targetInput;
        var limitName = $(this).attr("name");
        if (limitName) {
            var i = limitName.lastIndexOf('.Start');
            if (i > 0) {
                isMin = true;
                limitName = limitName.substr(0, i);
                targetInput = $('input:[name="' + limitName + '.End' + '"]');
            } else {
                i = limitName.lastIndexOf('.End');
                isMin = false;
                limitName = limitName.substr(0, i);
                targetInput = $('input:[name="' + limitName + '.Start' + '"]');
            }
        }
        if (!limitName) {
            limitName = $(this).attr('maxdate');
            if (limitName) {
                isMin = false;
                targetInput = $('input:[mindate="' + limitName + '"]');
            } else {
                limitName = $(this).attr('mindate');
                if (limitName) {
                    isMin = true;
                    targetInput = $('input:[maxdate="' + limitName + '"]');
                }
            }
        }
        return { isMin: isMin, targetInput: targetInput };
    };

    $('input[tag="date"]').datepicker(/*{ onSelect: limitDate }*/).attr('readonly', true);
    $('input[tag="datetime"]').attr('style', 'width:150px;').datetimepicker({ clockType: 24 }).attr('readonly', true);



    //反序列化字符串
    $.StringToJson = function (str) {
        var qsobj = {};
        var thisqs = str.split('?')[1];

        if (thisqs) {
            var pairs = thisqs.split('&');
            for (var i = 0; i < pairs.length; i++) {
                var pair = pairs[i].split('=');
                qsobj[pair[0]] = pair[1];
            }
        }
        return qsobj;
    };


    //select change显示指定元素
    $('select.showElement').change(function () {
        var id = this.id;
        $('*[forshow="' + id + '"]').hide();
        $('*[forshow="' + id + '"][showvalue="' + $(this).val() + '"]').show();
    });

    //a Button 效果
    $('a.Button').each(function () {
        var css = $(this).removeClass('Button').attr('class');
        $(this).addClass('Button');
        var content = $(this).html();
        $(this).empty().append('<span class="icon ' + css + '"/>').append($('<span class="content"/>').html(content));
    });

    $('div.topOperRegion>a.tb-btn:odd').each(function () {
        $('<span class="tb-btn-split"></span>').insertBefore(this);
    });

    //调试Log
    $.TraceEnabled = $.IsDebug = $('#_divDebug').length > 0;
    $.Trace = function (str) {
        $('#_divDebug').append(str + "<br />");
    };


    //提交form
    $('a.submit').click(function () {
        $(this).parents('form').submit();
        return false;
    });
    //取消超链接的虚线框
    $("a").focus(function () {
        this.blur();
    });

    //form输入验证
    $('form').submit(function () {
        return $(this).validate();
    });

    //Ajax情况下的Form验证
    $.extend($, {
        ajaxSubmit:
        {
            options:
            {
                beforeSubmit: function (arr, $form, options) {
                    if (!$form.validate()) return false;
                    var dlg = $form.parents('.ui-dialog');
                    if (dlg.length > 0) {
                        var buttons = $('.ui-button', dlg);
                        buttons.attr('disabled', 'disabled');
                        var oldsuccess = options.success;
                        options.success = function () {
                            oldsuccess.apply($form, arguments);
                            buttons.removeAttr('disabled');
                        };

                    }
                    return true;
                }
            }
        }
    });

    //全选复选框
    $('.datalist>thead>tr>td:first>:checkbox').live('click', function () {
        var checked = $(this).attr('checked');
        if (checked) {
            $('.datalist>tbody>tr>td:first-child>:checkbox').attr('checked', true);
        } else {
            $('.datalist>tbody>tr>td:first-child>:checkbox').removeAttr('checked');
        }
    });

    $.InitFlash = function () {
        //加载flash
        $('*[swf]').each(function () {
            var self = $(this);
            var fvars = self.attr('flashvars') || '';
            fvars = fvars.replace('{IP}', window.location.protocol + "//" + window.location.host);
            self.flash({ swf: self.attr('swf'), flashvars: fvars, height: self.attr('swfheight') || 320, width: self.attr('swfwidth') || 480, AllowScriptAccess: "always", Allowfullscreen: "true" });
        });
    };
    $.InitFlash();


    //========================查询分页=================================//
    //排序
    $('.datalist thead td[sort]').live('click', function () {
        var self = $(this);


        var oDataTable = $(this).parents('.datalist').parent();
        var strId = oDataTable.attr('id');
        var oAction = $('#' + strId.substr(0, strId.length - 4));
        //排序的字段
        var dataColumn = $(this).attr('sort');
        if (!dataColumn) return false;

        var query = oAction.data('query');

        //获取上一次排序的值
        var oldColumn = "";
        var bIsasc = true;
        if (query.OrderBy) {
            var arr = query.OrderBy.split(" ");
            oldColumn = arr[0];
            bIsasc = arr[1] == 'asc';
        }

        if (oldColumn == dataColumn) bIsasc = !bIsasc;
        var strOrder = (bIsasc ? "asc" : "desc");
        query.OrderBy = dataColumn + " " + strOrder;
        query.PageIndex = 1;
        oAction.data('query', query);
        window.loadpage(oAction);


    });
    //重新加载当前页
    $.fn.reloadPage = function () {
        window.loadpage(this);
    };
    //查询并转到第一页
    $.fn.search = function () {
        $(this).click();
    };

    var pageSummary = function () {

        if ($(".datalist").hasClass("totalSummary") == false) {
            return;
        }

        var recCnt = $(".datalist").attr("recordcount");
        if (recCnt == null) {
            return;
        }

        var tableEle = $("div.topOperRegion>table");
        var ele;
        if (tableEle.length < 1) {
            ele = $("div.topOperRegion>span.summary");
            if (ele.length < 1) {
                ele = $("<span class='summary'></span>");
                $("div.topOperRegion").append(ele);
            }

        }
        else {
            ele = $("div.topOperRegion>table>tbody>tr>td.summary");
            if (ele.length < 1) {
                ele = $("<td class='summary'></td>");
                $("div.topOperRegion>table>tbody>tr").append(ele);
            }

        }

        ele.html('共：' + recCnt + '条记录');

    };
    //回到顶部
    function BackTop() {
        $('html, body').animate({ scrollTop: 0 }, 500);
    };

    pageSummary();

    $('a.searchbtn').each(function () {
        var self = $(this);
        var oDataTable = $('#' + this.id + "Data");
        var pagedata = oDataTable.children();
        var oPage = $('#' + this.id + "Page");
        var query = {};
        query.pageindex = 1;
        query.pagesize = pagedata.attr("pagesize");
        self.data('query', query);

        //创建加载页面的方法
        if (!window.loadpage) {
            window.loadpage = function (ele) {
                var self = $(ele);
                if (self.length == 0) return;
                var oDataTable = $('#' + self.attr('id') + "Data");
                var oPage = $('#' + self.attr('id') + "Page");
                var query = self.data('query');
                query.pagesize = oPage.pages('getPagesize');
                oDataTable.load(self.attr('href'), query, function () {
                    var data = oDataTable.children();
                    oPage.pages('changepage', data.attr("pageindex"), data.attr("recordcount"));

                    pageSummary();

                    //显示排序信息
                    if (query.OrderBy) {
                        var arr = query.OrderBy.split(" ");
                        var oldColumn = arr[0];
                        var strOrder = ((arr[1] == 'asc') ? 'asc' : 'desc');
                        $('thead td[sort="' + oldColumn + '"]', data).addClass(strOrder).append('<img src="/Content/Images/' + strOrder + '.png"/>');
                    }
                    self.trigger('ajaxload');
                    stripe();
                    BackTop();
                });
            };
        }


        oPage.pages({ pageindex: pagedata.attr("pageindex"), total: pagedata.attr("recordcount"), max: 10, pagesize: query.pagesize,
            onpage: function (ui) {
                var query = self.data('query');
                query.pageindex = ui.index;
                self.data('query', query);
                window.loadpage(self);
            }
        });

    });

    //查询搜索
    $('a.searchbtn').click(function () {
        var self = $(this);

        // var limitDays = $('input[tag="date"][name$=".Start"][limit]', self.parent()).attr('limit');

        var items = $(':input', self.parent()).SerializeElements();
        var dateCtls = $('input[tag="date"][name$=".End"]', self.parent());

        dateCtls.each(function () {
            if ($.trim($(this).val()) != '') {
                var date = $(this).datepicker("getDate");
                date.setDate(date.getDate() + 1);
                var str = $.datepicker.formatDate($.datepicker._defaults.dateFormat, date);
                items[this.name] = str;
            }
        });




        var query = $.extend({}, self.data("query"), items, { pageindex: 1 });
        self.data('query', query);
        window.loadpage(this);
        return false;
    });

    //========================查询分页结束=================================//

    //点击隐藏
    $(':checkbox.checkhide').bind('click change', function () {
        var checked = $(this).attr('checked');
        if ($(this).hasClass('reverse')) checked = !checked;
        if (checked)
            $('*[forid="' + this.id + '"]').show(); else
            $('*[forid="' + this.id + '"]').hide();
    });


    $(':checkbox.checkhide').each(function () {
        $(this).triggerHandler('click');
    });


    //弹出层显示ajax信息
    var popmove = function () {
        var self = $(this);
        self.die('mousemove', popmove);
        var aid = self.attr('id');
        var pop = $('#' + aid + 'Pop');
        var loadEle;
        if (pop.hasClass('loadcontent')) {
            loadEle = pop;
        } else {
            loadEle = $('.loadcontent', pop);
        }
        if (loadEle.attr('onloading')) {
            return false;
        } else {
            loadEle.waiting().attr('onloading', true).load(this.href, function () {
                loadEle.removeAttr('onloading');
            });
        }
        pop.offset(self.offset()).css('zIndex', self.zIndex() + 1).show();
        pop.one('mouseleave', function () {
            $(this).hide();
        });
        return false;
    };
    $('a.popshow').live('mousemove', popmove);



    $.CheckActionResponse = function (data, module, chargeType, postback) {
        if (data.GoAhead) {
            postback();
        }
        else {
            if (!alertEle) {
                alertEle = $('<div id="ico" style="display:none"><div id="img"></div></div>').appendTo($(document.body));
            }
            var title = '提示';
            var Msg = "您当前的余额为：￥" + data.UserBlance + "元";
            $('p', alertEle).remove();
            if (data.HasDeductionType && data.LengthAmount != 0 && data.Price == null) {

                Msg = Msg + ",将按照标准资费扣除：￥" + data.LengthAmount + "元，购买套餐更加优惠！";
            }
            if (data.AlertBuyBag) {
                Msg = Msg + ",您的套餐可用数量不足且系统中不存在该扣费的标准资费，请先购买套餐！";
            }
            if (data.Price != null) {
                Msg = Msg + ",本次将按标准资费扣费，扣费标准：" + data.Price + ",购买套餐更加优惠!";
            }
            if (!data.MoneyEnough) {
                Msg += ",您当前的余额不足，请充值！";
            }

            $('<p>' + Msg + '</p>').insertAfter($('#img', alertEle));
            $('#img', alertEle).removeClass().addClass('tipInfo');



            if (!data.MoneyEnough) {
                alertEle.dialog({
                    title: '【' + title + '】',
                    autoOpen: false,
                    width: 500,
                    modal: true,

                    buttons: {
                        "关闭": function () {
                            $(this).dialog("close");
                        },

                        "充值": function () {
                            window.location = "/Public/Account/Deposit";
                            $(this).dialog("close");
                        }
                    }
                });
                return alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');

            }

            if (data.HasDeductionType && data.LengthAmount != 0) {
                alertEle.dialog({
                    title: '【' + title + '】',
                    autoOpen: false,
                    width: 500,
                    modal: true,

                    buttons: {
                        "关闭": function () {
                            $(this).dialog("close");
                        },

                        "继续": function () {
                            postback();
                            $(this).dialog("close");
                        },
                        "购买套餐": function () {
                            var urlBuy = "/Fee/BagTariff/Index?";
                            urlBuy = RegularUrl(urlBuy, 'Module', module);
                            urlBuy = RegularUrl(urlBuy, 'ChargeType', chargeType);
                            window.location = urlBuy;
                            $(this).dialog("close");
                        }
                    }
                });
                return alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');

            }

            if (data.AlertBuyBag) {
                alertEle.dialog({
                    title: '【' + title + '】',
                    autoOpen: false,
                    width: 500,
                    modal: true,

                    buttons: {
                        "关闭": function () {
                            $(this).dialog("close");
                        },

                        "购买套餐": function () {
                            var urlBuy = "/Fee/BagTariff/Index?";
                            urlBuy = RegularUrl(urlBuy, 'Module', module);
                            urlBuy = RegularUrl(urlBuy, 'ChargeType', chargeType);
                            window.location = urlBuy;
                            $(this).dialog("close");
                        }
                    }
                });
                return alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');

            }
            //            if (data.TimesAmount != 0 && data.LengthAmount != 0) {
            //                
            //                alertEle.dialog({
            //                    title: '【' + title + '】',
            //                    autoOpen: false,
            //                    width: 500,
            //                    modal: true,

            //                    buttons: {
            //                        "关闭": function() {
            //                            $(this).dialog("close");
            //                        },

            //                        "继续": function() {
            //                            postback();
            //                            $(this).dialog("close");
            //                        },
            //                        "购买套餐": function() {
            //                            var urlBuy = "/Fee/BagTariff/Index?";
            //                            urlBuy = RegularUrl(urlBuy, 'Module', module);
            //                            urlBuy = RegularUrl(urlBuy, 'ChargeType', chargeType);
            //                            window.location = urlBuy;
            //                            $(this).dialog("close");
            //                        }
            //                    }
            //                });
            //                return alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');
            //                
            //            }
        }


    };



    $.ActionResponse = function (icontype, title, content, callback, cancelcallback) {
        if (!alertEle) {
            //            alertEle = $('<div id="ico"><div id="content"></div></div>').appendTo($(document.body));
            alertEle = $('<div id="ico"><div id="img"></div></div>').appendTo($(document.body));
        }
        if (title == '') title = '提示';
        $('p', alertEle).remove();
        $('<p>' + content + '</p>').insertAfter($('#img', alertEle));
        //$('#content', alertEle).html(content);
        switch (icontype) {
            case 'success':
                $('#img', alertEle).removeClass().addClass('tipTrue');
                break;
            case 'error':
                $('#img', alertEle).removeClass().addClass('tipFalse');
                break;
            case 'alert':
                $('#img', alertEle).removeClass().addClass('tipAlert');
                break;
            case 'infomation':
                $('#img', alertEle).removeClass().addClass('tipInfo');
                break;
            default:
                $('#img', alertEle).removeClass().addClass('tipInfo');
        }
        if ($.isFunction(callback)) {
            alertEle.dialog({
                title: '【' + title + '】',
                autoOpen: false,
                width: 400,
                modal: true,
                buttons: {
                    "取消": function () {
                        $(this).dialog("close");
                        if (cancelcallback) cancelcallback();
                    },
                    "确定": function () {
                        $(this).dialog("close");
                        callback();
                    }
                }
            });
        } else {
            alertEle.dialog({
                title: '【' + title + '】',
                autoOpen: false,
                width: 400,
                modal: true,

                buttons: {
                    "关闭": function () {
                        $(this).dialog("close");
                    }
                }
            });
        }
        alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');
    };

    $.CheckStandardTariff = function (Tag, Msg, postback, obj) {
        if (!alertEle) {
            alertEle = $('<div id="ico"><div id="img"></div></div>').appendTo($(document.body));
        }
        var title = '提示';
        $('p', alertEle).remove();
        $('<p>' + Msg + '</p>').insertAfter($('#img', alertEle));
        $('#img', alertEle).removeClass().addClass('tipInfo');
        if (Tag == 2) {
            alertEle.dialog({
                title: '【' + title + '】',
                autoOpen: false,
                width: 400,
                modal: true,
                buttons: {
                    "关闭": function () {
                        window.location = obj.homeUrl;
                        $(this).dialog("close");
                    },
                    "购买套餐": function () {
                        var urlBuy = "/Fee/BagTariff/Index?";
                        urlBuy = RegularUrl(urlBuy, 'Module', obj.module);
                        urlBuy = RegularUrl(urlBuy, 'ChargeType', obj.chargeType);
                        urlBuy = RegularUrl(urlBuy, 'ResLevel', obj.level);
                        window.location = urlBuy;
                        $(this).dialog("close");
                    },
                    "充值": function () {
                        window.location = "/Public/Account/Deposit";
                        $(this).dialog("close");
                    }
                },
                closeOnEscape: false,
                open: function (event, ui) { $(".ui-dialog-titlebar-close").hide(); }
            });
            alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');
            return false;
        }
        if (Tag == 1) {
            alertEle.dialog({
                title: '【' + title + '】',
                autoOpen: false,
                width: 400,
                modal: true,

                buttons: {
                    "关闭": function () {
                        window.location = obj.homeUrl;
                        $(this).dialog("close");
                    },
                    "继续": function () {
                        $(this).dialog("close");
                        postback();
                        $(this).dialog("close");
                    },
                    "购买套餐": function () {
                        window.location = '/Fee/BagTariff';
                        $(this).dialog("close");
                    }
                },
                closeOnEscape: false,
                open: function (event, ui) { $(".ui-dialog-titlebar-close").hide(); }
            });
            alertEle.dialog('option', 'title', '【' + title + '】').dialog('open');
            return false;
        }
        if (Tag == 0) {
            postback();
        }

    };


    $.fn.overlay = function () {
        //var opts = $.extend({}, $.fn.pager.defaults, options);
        var el = this;
        el.options = {};
        el.$el = $.ui.dialog.overlay.create(el);
        //        el.$el = new $.ui.dialog.overlay(el);
        el.destoryoverlay = function () { $.ui.dialog.overlay.destroy(el.$el); };
        return el;
    };


    //等待状态
    $.waiting = {
        show: function (msg) {
            if (!msg) {
                msg = "正在加载中，请稍后......";
            }
            if (!window.message) window.message = {};
            if (!window.message.waiting) {
                window.message.waiting = $('<div class="wait" style="position: absolute;z-index:9999"><img src="/Content/Images/waiting.gif" /><span>' + msg + '</span></div>').appendTo(document.body);
            }
            window.message.waiting.overlay().offset({ top: 0, left: 0 }).css('display', '').position({
                of: window,
                my: 'center center',
                at: 'center center',
                offset: '',
                using: function (pos) {
                    var topOffset = $(this).css(pos).offset().top;
                    if (topOffset < 0) {
                        $(this).css('top', pos.top - topOffset);
                    }
                },
                collision: 'fit'
            }).show();
        },
        hide: function () {
            window.message.waiting.hide().destoryoverlay();
        }
    };
    $.fn.waiting = function (msg) {
        if (!msg) {
            msg = "正在加载中，请稍后......";
        }
        return $(this).empty().append('<img src="/Content/Images/waiting.gif" /><span>' + msg + '</span>');
    };

    var initTableLayout = function () {

        var self = $('div.topOperRegion:not(:has(a))').next('div.datacontainer');
        $('table.datalist:first', self).attr('style', 'border-top:0');
        $('div.topOperRegion:not(:has(a))').hide();
    }

    var stripe = $.stripe = function () {
        $('.datalist>tbody>tr:even').children('td').addClass('alt');
        initTableLayout();
        //datalist数据表格鼠标悬停变色
        $('.datalist>tbody>tr>td').live("mouseover", function () {
            $(this).parent('tr').children('td').addClass('over');
        }).live('mouseout', function () {
            $(this).parent('tr').children('td').removeClass('over');
        });
        //$('div.TableRegion').removeShadow().dropShadow({ blur: 1, swap: false, opacity: .5, color: "#999" });

        $('.datalist thead td[sort]').mousedown(function () {
            $(this).addClass('active');
        }).mouseup(function () {
            $(this).removeClass('active');
        });

        //按钮title提示
        $('a.Edit').attr('title', "编辑");
        $('a.Add').attr('title', "新增");
        $('a.Del').attr('title', "删除");
        $('a.Disabled').attr('title', '禁用');
        $('a.Enabled').attr('title', '启用');
        $('a.ImageAudit').attr('title', '审核');
        $('a.Password').attr('title', '修改密码');
        $('a.ImageReSend').attr('title', '重发');
        $('a.Meet').attr('title', '会见');
        $('a.View').attr('title', '查看');
        $('a.ImageSearch').attr('title', '查询');
        $('a.Reply').attr('title', '回复');
    };
    $.tip = function () {
        $('*[tip]').each(function () {
            var str = $.trim($(this).text());
            var len = parseInt($(this).attr("tip"));
            $(this).attr("title", str).removeAttr("tip");
            if (str.length > len) {
                $(this).text(str.substr(0, len) + "...");
            }
        });
    };
    var initInput = function () {
        var vdt = $(':input[required],select[required]').parent('dd').prev('dt');
        $('label', vdt).before('<span class="required">*</span>');

        $(':input[required],:input[datatype],:input[maxNum],textarea[maxlength], :input[date],input[tag^="date"]').focus(function () {
            $(this).InputTip();
        }).blur(function () {
            $(this).validateele();
        });

        $(':input[maxlength]').keypress(function () {
            var self = $(this);
            var len = self.attr('maxlength');
            if (len) {
                var str = self.val();
                if (str.length > len) {
                    self.validatemsg("最多允许输入" + len + "个字符");
                    return false;
                } else {
                    self.validatemsg("", true);
                }

            }
        });

    };


    $.fn.SerializeElements = function (skipempty) {
        var items = {};
        this.each(function () {
            var fieldname = $(this).attr('datafield') || this.name;
            if (fieldname) {
                var self = $(this);
                if (self.is(':checkbox') || self.is(':radio')) {
                    if (self.attr('checked'))
                        items[fieldname] = $(this).val();
                } else {
                    var val = self.val();
                    if (!self.is(':input')) {
                        val = val || $.trim(self.text());
                    }
                    if (val.length == 0 && skipempty) return;
                    items[fieldname] = val;
                }
            }
        });
        return items;
    };


    $.fn.validatemsg = function (str, success) {

        var ele = this.parent();
        ele.find('span.ErrorTip,span.InputTip').remove();
        if (success) {
            //ele.append($(' <span class="noteCheck true"></span>'));
            return false;
        } else {
            if (this.attr('alert')) {
                $.ActionResponse('error', '提示', this.attr('alert'));
            } else
                this.after('<span class="ErrorTip">' + str + '</span>');
        }
        return true;

    };
    $.fn.resetvalidate = function () {
        this.find('span.ErrorTip').remove();
        return this;
    };
    $.fn.removevalidatemsg = function () {
        var ele = this.parent();
        ele.find('span.ErrorTip').remove();
    };
    $.validate = {};
    $.validate.regexEnum = {
        intege: "^-?[0-9]\\d*$", 				//整数
        intege1: "^[1-9]\\d*$", 				//正整数
        intege2: "^-[1-9]\\d*$", 				//负整数
        num: "^([+-]?)\\d*\\.?\\d+$", 		//数字
        num1: "^[1-9]\\d*|0$", 				//正数（正整数 + 0）
        num2: "^-[1-9]\\d*|0$", 				//负数（负整数 + 0）
        decmal: "^([+-]?)\\d*\\.\\d+$", 		//浮点数
        decmal1: "^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$", //正浮点数
        decmal2: "^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$", //负浮点数
        decmal3: "^-?([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0)$", //浮点数
        decmal4: "^\d+(\.\d+)?$", //非负浮点数（正浮点数 + 0）
        decmal5: "^((-\d+(\.\d+)?)|(0+(\.0+)?))$", //非正浮点数（负浮点数 + 0）

        email: "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$", //邮件
        color: "^[a-fA-F0-9]{6}$", 			//颜色
        url: "^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$", //url
        chinese: "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$", 				//仅中文
        ascii: "^[\\x00-\\xFF]+$", 			//仅ACSII字符
        zipcode: "^\\d{6}$", 					//邮编
        mobile: "^(13|14|15|18)[0-9]{9}$", 			//手机
        ip4: "^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$", //ip地址
        notempty: "^\\S+$", 					//非空
        picture: "(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$", //图片
        rar: "(.*)\\.(rar|zip|7zip|tgz)$", 							//压缩文件
        xls: "(.*)\\.(xls|xlsx)$",
        date: "^\\d{4}(\\-|\\/|\.)\\d{1,2}\\1\\d{1,2}$", 				//日期
        qq: "^[1-9]*[1-9][0-9]*$", 			//QQ号码
        tel: "^(([0\\+]\\d{2,3}-)?(0\\d{2,3})-)?(\\d{7,8})(-(\\d{3,}))?$", //电话号码的函数(包括验证国内区号,国际区号,分机号)
        username: "^\\w+$", 					//用来用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
        letter: "^[A-Za-z]+$", 				//字母
        letter_u: "^[A-Z]+$", 				//大写字母
        letter_l: "^[a-z]+$", 				//小写字母
        idcard: "^[1-9]([0-9]{14}|[0-9]{17})$", //身份证
        filepath: "^[a-z]:(//||\\\\)[\\w\\u4e00-\\u9fa5\\s]+((([/\\\\][\\w\\u4e00-\\u9fa5\\s]+)*$)||$)" //文件路径
    };
    $.validate.regexEnumMsg = {
        all: "请输入",
        intege: "输入大于等于0的整数", 				//整数
        intege1: "输入大于0的整数", 				//正整数
        intege2: "输入小于0的整数", 				//负整数
        num: "输入整数或带小数点的数字", 		//数字
        num1: "输入正数", 				//正数（正整数 + 0）
        num2: "输入负数", 				//负数（负整数 + 0）
        decmal: "输入带小数点的数字", 		//浮点数
        decmal1: "输入带小数点的正数", //正浮点数
        decmal2: "输入带小数点的负数", //负浮点数
        decmal3: "输入带小数点的数字", //浮点数
        decmal4: "非负浮点数", //非负浮点数（正浮点数 + 0）
        decmal5: "^((-\d+(\.\d+)?)|(0+(\.0+)?))$", //非正浮点数（负浮点数 + 0）

        email: "^输入邮箱", //邮件
        color: "^[a-fA-F0-9]{6}$", 			//颜色
        url: "^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$", //url
        chinese: "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$", 				//仅中文
        ascii: "^[\\x00-\\xFF]+$", 			//仅ACSII字符
        zipcode: "^\\d{6}$", 					//邮编
        mobile: "输入手机号", 			//手机
        ip4: "^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$", //ip地址
        notempty: "^\\S+$", 					//非空
        picture: "(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$", //图片
        rar: "(.*)\\.(rar|zip|7zip|tgz)$", 							//压缩文件
        xls: "xls文件",
        date: "^\\d{4}(\\-|\\/|\.)\\d{1,2}\\1\\d{1,2}$", 				//日期
        qq: "输入QQ号", 			//QQ号码
        tel: "[区号-]号码[-分机号]", //如：[0531-]8888888[-123]，[]里的内容可选//电话号码的函数(包括验证国内区号,国际区号,分机号)
        username: "^\\w+$", 					//用来用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
        letter: "^[A-Za-z]+$", 				//字母
        letter_u: "^[A-Z]+$", 				//大写字母
        letter_l: "^[a-z]+$", 				//小写字母
        idcard: "输入身份证号", //身份证
        filepath: "请输入文件路径,如D:\\SDCM\\BackUp" //文件路径
    };
    $.fn.InputTip = function (message) {
        var self = $(this);
        self.nextAll('span.ErrorTip,span.InputTip').remove();

        var datatype = self.attr('datatype') || self.attr('required');
        if (datatype == '*') datatype = 'all';

        var msg = message || self.attr('inputtip') || $.validate.regexEnumMsg[datatype] || "";
        //span.InputTip

        //var reqEle = self.attr('required') ? self.next('span.required') : self;
        self.after('<span class="InputTip">' + msg + '</span>');
    };
    initInput();
    //$(':input[required]').parent().prev('dt').after('<span class="required">*</span>');

    $.fn.validateele = function () {
        var self = $(this);
        //移除输入提示
        $(this).validatemsg('a', true);

        var elename = self.attr['elename'] || $('label:first', self.parent('dd').prev('dt')).text().replace(':', '').replace('：', '').replace(' ', '');

        //检测元素有没有绑定onvalidate事件，如果绑定了则使用元素自定义的验证方案
        var event = jQuery.Event("onvalidate");
        self.trigger(event);
        if (event.result) {
            if (event.result.success)
                return true;
            else {
                self.validatemsg(event.result.msg);
                return false;
            }
        }

        //是否跳过隐藏域的验证
        if (self.is(':hidden') && self.attr('skip') != "no") return true;
        var isRequired = self.attr('required');
        var datatype = self.attr('datatype');

        //检测时间范围
        if (self.attr("tag") == "datetime" || self.attr("tag") == "datetime") {
            if (self.val() != '') {
                var option = self.getContraryDate();
                var t = option.targetInput;
                if (t.length > 0) {
                    if (t.val() != '') {
                        var date = self.datepicker("getDate");
                        var targetdate = t.datepicker("getDate");
                        if (date < targetdate != option.isMin) {
                            if (option.isMin) {
                                t.validatemsg("日期范围错误");
                            } else {
                                self.validatemsg("日期范围错误");
                            }
                            return false;
                        }

                    }
                }
            }
        }

        //检测是否超出长度

        if (self.is("textarea")) {
            var len = self.attr('maxlength');
            if (len) {
                var str = self.val();
                if (str.length > len) {
                    self.validatemsg("最多允许输入" + len + "个字符");
                    return false;
                }
            }

        }
        //检测大于某整数
        if (self.is("input")) {
            var num = self.attr('maxNum');
            if (num) {
                var str = self.val();
                if (eval(str) > eval(num)) {
                    self.validatemsg("最大数为" + num);
                    return false;
                }
            }

        }


        if (!isRequired && !datatype) return true;
        if (!isRequired && self.val() == '') return true;

        if (isRequired && isRequired != '*') {
            datatype = datatype || isRequired;
        }
        var vMsg = self.attr['inputmsg'];
        if (isRequired && self.is(":text,:file,input:hidden,textarea,:password") && self.val() == '') {
            if (self.is(":file")) {
                self.validatemsg(vMsg || '请选择文件！');
            } else {
                self.validatemsg(vMsg || '请输入' + elename);
            }
            return false;
        } else if (self.is(':radio')) {
            var eles = $.radio(self.attr("name"));
            if (!eles.val()) {
                eles.last().validatemsg(vMsg || '请选择' + elename);
                return false;
            } else {
                return true;
            }

        } else if (self.is('select')) {
            if (self.val() == '') {
                self.validatemsg(vMsg || '请选择' + elename);
                return false;
            }
            return true;
        } else {
            if (!datatype || datatype == '*') return true;
            var regexpress = eval("$.validate.regexEnum." + datatype);
            if ((new RegExp(regexpress, "i")).test(self.val())) {
                return true;
            }
            self.validatemsg(elename + '输入格式不正确');
            return false;
        }
    };
    $.fn.validate = function () {
        if (this.length == 1 && this.is('form')) {
            return this.find(':input').validate();
        }
        var ret = true;
        this.each(function () {
            if (!$(this).validateele()) {
                ret = false;
                return ret;
            } else {
                if ($(this).attr('required'))
                    $(this).validatemsg('a', true);
                else
                    $(this).removevalidatemsg();

            }
        });
        return ret;

    };



    //绑定autocomplete //TODO:to be continue
    $.autocomplete = {
        split: function (val) {
            return val.split(/[,，]\s*/);
        },
        extractLast: function (term) {
            return $.autocomplete.split(term).pop();
        },
        //去除无效数据
        validate: function (ele) {
            var valfield = ele.attr('valuefield');
            var disfield = ele.attr('displayfield') || valfield;
            var terms = $.autocomplete.split(ele.val());
            //检查数据的有效性
            var data = ele.data('selectdata') || [];

            //去掉terms里没有的数据
            data = $.grep(data, function (n, i) {
                for (var j in terms) {
                    if (terms[j] == $.getDataByTemplate(n, disfield)) {
                        return true;
                    }
                }
                return false;
            });
            //去掉无效term
            terms = $.grep(terms, function (n, i) {
                for (var i in data) {
                    if (n == $.getDataByTemplate(data[i], disfield)) {
                        return true;
                    }
                }
                return false;
            });

            ele.data('selectdata', data);
            //            //转换为提交数据
            //            ele.toSubmitData(data);
            return terms;
        },

        init: function () {
            var eles = $(":text.autocomplete").autocomplete({
                source: function (request, response) {
                    //var self = this;
                    var ele = this.element;

                    var term = ele.attr('searchfield') || ele.attr('displayfield') || 'term';
                    var oQuery = { PageIndex: 1, PageSize: ele.attr('pagesize') || 5 };
                    oQuery[term] = $.autocomplete.extractLast(request.term);
                    $.getJSON(ele.attr('href'), oQuery,
                       function (data) {
                           response(data.Data || data);
                       });
                },
                search: function () {
                    // custom minLength
                    var term = $.autocomplete.extractLast(this.value);
                    //检测是否和上次输入的一样
                    var oldterm = this._previnput;
                    if ($.trim(this.value) == oldterm) {
                        return false;
                    }
                    this._previnput = this.value;

                    if (term.length < 2) {
                        return false;
                    }
                },
                focus: function () {
                    // prevent value inserted on focus
                    return false;
                },
                select: function (event, ui) {
                    var ele = $(this);

                    var valfield = ele.attr('valuefield');
                    var disfield = ele.attr('displayfield') || valfield;
                    var terms = $.autocomplete.split(this.value);
                    // remove the current input
                    terms.pop();
                    terms = $.autocomplete.validate(ele);
                    var data = ele.data('selectdata') || [];
                    var isCanAdd = true;
                    for (var i in data) {
                        //如果已经存在则返回
                        if (ui.item[valfield] == data[i][valfield]) {
                            isCanAdd = false;
                            break;
                        }
                    }
                    if (isCanAdd) {
                        // add the selected item
                        terms.push($.getDataByTemplate(ui.item, disfield));
                        data.push(ui.item);
                    }
                    // add placeholder to get the comma-and-space at the end
                    terms.push("");
                    this.value = terms.join(",");
                    ele.attr('title', this.value);
                    ele.data('selectdata', data);

                    //转换为提交数据
                    //ele.toSubmitData(data);


                    //                    if ($.TraceEnabled) {
                    //                        $.Trace('----------------------');
                    //                        for (var i in data) {
                    //                            $.Trace($.getDataByTemplate(data[i], disfield));
                    //                        }
                    //                    }



                    return false;
                }
            });
            if (eles.length > 0) {
                eles.blur(function () {
                    var ele = $(this);
                    var terms = $.autocomplete.validate(ele);
                    terms.push("");
                    this.value = terms.join(",");
                    ele.attr('title', this.value);
                    var data = ele.data('selectdata');
                    ele.toSubmitData(data);
                    $(this).InputTip('已将无效内容移除');
                });
                eles.data("autocomplete")._renderItem = function (ul, item) {
                    var ele = this.element;
                    var template = $('#' + ele.attr("id") + "Template").html() || "<a>{{" + (ele.attr('displayfield') || ele.attr('valuefield')) + "}}</a>";
                    return $("<li></li>")
				.data("item.autocomplete", item)
				.append($.getDataByTemplate(item, template))
				.appendTo(ul);
                };
            }

        }
    };
    $.autocomplete.init();

    //清空数据
    $.fn.resetInput = function () {
        var eles = $(":input", this);
        if (eles.length == 0) eles = this;
        return eles.each(function () {

            var self = $(this);
            if (self.is(":checkbox") || self.is(':radio')) return;
            if (this.name == "Id")
                self.val(0);
            else
                self.val(self.attr('defaultval') || "");
        });


    };

    //绑定dialog数据
    $.fn.bindDlgData = function (href, callback, defaultFieldNameSpace) {
        $.waiting.show();
        this.resetInput();
        var ele = this;
        ele.resetvalidate();
        $('.edithide', ele).hide();

        $.post(href, {}, function (data) {
            $(':input[name],*[datafield]', ele).binddata(data, defaultFieldNameSpace);
            $.waiting.hide();
            ele.dialog('open');
            if ($.isFunction(callback)) { callback(data); }
        }, 'json');

    };

    $.fn.bindDlgHtml = function (href, callback) {
        $.waiting.show();
        var ele = this;
        ele.resetvalidate();
        $('div.content', ele).load(href, function () {
            initInput();
            $.waiting.hide();
            ele.dialog('open');
            if ($.isFunction(callback))
                callback();
        });
    };

    //TODO:修改form.submit监听方法，将 $(ele).data('submitdata')变成 <input type="hidden" name="[datafield][0].[valuefield]" value="1" />
    //传入一个对象数组，并且当前元素上有displayfield,valuefield属性,并将Value绑定到this.data('submitdata')={"[datafield][0].[valuefield]"=value1,"[datafield][1].[valuefield]"=value1}里
    $.fn.bindArray = function (data) {
        var displayfield = this.attr('displayfield');
        var strDisplay = "";
        if (displayfield) {
            for (var i = 0; i < data.length; i++) {
                var item = data[i];
                strDisplay += $.getDataByTemplate(item, displayfield) + ",";
            }
        }
        this.val(strDisplay);
        this.toSubmitData(data);
    };
    //将数据转换为提交数据
    $.fn.toSubmitData = function (data) {
        var valuefield = this.attr('valuefield');
        var datafield = this.attr('datafield');
        if (!valuefield) return false;
        this.data('selectdata', data);
        var prefix = this.attr('id') + "_data";
        $('input:hidden.' + prefix).remove();

        for (var i = 0; i < data.length; i++) {
            var item = data[i];
            var obj = {};
            obj.name = datafield + '.' + valuefield; // +'[' + i.toString() + '].' + valuefield;
            obj.value = $.getDataByTemplate(item, valuefield);
            this.after($('<input type="hidden" />').attr(obj).addClass(prefix));
        }
        //        if ($.TraceEnabled) {
        //            $.Trace('----------------------');
        //            $('input:hidden.' + prefix).each(function() {
        //                $.Trace($(this).attr('name') + ":" + $(this).val());
        //            })
        //        }

    };

    //解析数据模板
    $.getDataByTemplate = function (data, template, defaultFieldNameSpace) {
        var getData = function (data, field) {
            if (defaultFieldNameSpace && field.indexOf(".") <= 0) {
                field = defaultFieldNameSpace + "." + field;
            }
            var item = data;
            var arrFields = field.split(".");
            for (var i = 0; i < arrFields.length; i++) {
                item = item[arrFields[i]];
                if (item == null || item == undefined) {
                    break;
                }
            }
            if (item == undefined) {
                item = null;
            }
            return item;
        };
        var item;
        //替换例如 datafield="部门:{{Department.Name}}"的表达式
        var re = /\{\{([^\}]*)\}\}/g;
        if (re.test(template)) {
            item = template.replace(re, function () {
                return getData(data, arguments[1]) || "";
            });
        } else {
            //简单的替换 datefield="Department.Name"类型的值
            item = getData(data, template);
        }
        return item;
    };


    //绑定数据
    $.fn.binddata = function (data, defaultFieldNameSpace) {
        if (!data) return false;
        //绑定数据到页面元素
        //defaultFieldPrefix,如果没有前面的名字则使用默认的名字，如"aa"则成为"name.aa","aa.bb"则不变
        return this.each(function () {
            var self = $(this);
            var field = $(this).attr("datafield") || this.name;

            if (field == undefined || field == null || field == "") return;


            var item = $.getDataByTemplate(data, field, defaultFieldNameSpace);

            if (self.is(':checkbox')) {
                if (item != null && (item == true || item == "1" || item.toString().toLowerCase() == "true")) {
                    self.attr("checked", true);
                } else {
                    self.removeAttr("checked");
                }

            } else if (self.is(':radio')) {
                if (item != null && this.value == item.toString()) {
                    self.attr("checked", true);
                }
            } else if (self.is('select')) {
                var subitem = self.children('option[value="' + item + '"]');
                if (subitem.length == 0) {
                    self.attr('selval', item);
                } else {
                    self.removeAttr('selval').val(item);
                }
            } else {
                if (item != null) {
                    //处理日期数据
                    if (item.getDate) {
                        var str = item.format(self.attr('format') || 'isoDate');
                        if (self.is(':input'))
                            self.val(str);
                        else
                            self.text(str);
                    } else {
                        if (self.is(':input')) {
                            //如果是数组并且定义了数组显示规则
                            if ($.isArray(item) && self.attr('displayfield'))
                                self.bindArray(item);
                            else
                                self.val(item);
                        }
                        else {
                            self.text(item);
                        }
                    }

                } else {
                    self.val('');
                }
            }
            self.change();

        });
    };




    stripe();
});

(function () {
    function jRadio(name) {
        this.elements = $('input[type=radio][name=' + name + ']');
        this.lastVal = jRadio.prototype.val.apply(this);
    }
    jRadio.prototype.last = function () {
        return $(this.elements[this.elements.length - 1]);
    };
    jRadio.prototype.change = function (callback) {
        var self = this;
        this.elements.click(function () {
            var val = self.val();
            if (val != self.lastVal) {
                self.lastVal = val;
                callback(self);
            }
        })
    }
    jRadio.prototype.val = function (val) {
        if (val === undefined) {
            return this.elements.filter(function () { return this.checked; }).val();
        } else {
            if (this.lastVal == val) return;
            this.lastVal = val;
            this.elements.filter(function () { return $(this).val() == val; }).attr('checked', true);
            return this;
        }
    }

    $.radio = function (name) {
        return new jRadio(name);
    }
})();

String.prototype.isEmail = function () {
    var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
    return reg.test(this);
}
String.prototype.len = function () {
    return this.replace(/[^\x00-\xff]/g, "**").length;
}
String.prototype.toJSON = function () {
    return eval("(" + this + ")");
}



/*
jqURL
by Josh Nathanson

various manipulations on url strings and windows.  
all functions can also take a window object as an argument,
for example {win:opener}
but will default to current window if none is passed.

public functions:

-------------------------
.url({ 
win:window object 
})
-------------------------
returns the whole url string
like win.location.href

so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"
	
$.jqURL.url() returns "http://www.mysite.com?var1=1&var2=2&var3=3"
	
	
------------------------------
.loc(urlstr:string, 
{ 
win:window object, 
w:integer, 
h:integer, 
t:integer,
l:integer,
wintype:string('_top'[default],'_blank','_parent') )
})
------------------------------																			 
- directs passed in window to urlstr, which is required
- works like window.location.href = 'myurl'
- but you can also use it to pop open a new window by passing in "_blank" as the wintype
- if popping open a window, defaults to center of screen

so
$.jqURL.loc('http://www.google.com',
{w:200,h:200,wintype:'_blank'});
would open Google in a new centered 200x200 window
	
or, locate an url to any named window:
$.jqURL.loc('http://www.google.com',{ win:mywindow });
opens Google in mywindow


------------------------------
.qs({ 
ret:string('string'[default],'object'), 
win:window object })
------------------------------
returns querystring, either string (pass ret:'string' [default])
or object (pass ret:'object') 

so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"

$.jqURL.qs();
returns "var1=1&var2=2&var3=3"
	
$.jqURL.qs({ ret:'object' });
returns Object var1=1,var2=2,var3=3


------------------------------
.strip({ keys:string(list of keys to strip), win:window object })
------------------------------
if passed with no arguments, returns url with '?' and query string removed
if you pass in list of keys, it returns url with the specified key-value pairs removed

so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"

$.jqURL.strip();
will return
"http://www.mysite.com"
	
$.jqURL.strip({ keys:'var1,var2' });
will return
"http://www.mysite.com?var3=3"
	
	
-------------------------------------
.get(key, {win:window object})
-------------------------------------
returns value of passed in querystring key

so if the current window href is "http://www.mysite.com?var1=1&var2=2&var3=3"
$.jqURL.get('var2');
will return 2

--------------------------------------
.set(hash, {win:window object})
--------------------------------------
returns the window's url, but with the keys/values set in the query string
if the keys already exist, re-sets the value
if they don't exist, they're appended onto the query string

*/

jQuery.jqURL = {

    url: // returns a string
	function (args) {
	    args =
			jQuery.extend({
			    win: window
			},
			args);
	    return args.win.location.href;
	},

    loc:
	function (urlstr, args) {
	    args =
			jQuery.extend({
			    win: window,
			    w: 500,
			    h: 500,
			    wintype: '_top'
			},
			args);

	    if (!args.t) {
	        args.t = screen.height / 2 - args.h / 2;
	    }
	    if (!args.l) {
	        args.l = screen.width / 2 - args.w / 2;
	    }
	    if (args['wintype'] == '_top') {
	        args.win.location.href = urlstr;
	    }
	    else {
	        open(
			urlstr,
			args['wintype'],
			'width=' + args.w + ',height=' + args.h + ',top=' + args.t + ',left=' + args.l + ',scrollbars,resizable'
			);

	    }
	    return;
	},

    qs:
	function (args) {
	    args = jQuery.extend({
	        ret: 'string',
	        win: window
	    },
		args);

	    if (args['ret'] == 'string') {
	        return jQuery.jqURL.url({ win: args.win }).split('?')[1];
	    }

	    else if (args['ret'] == 'object') {

	        var qsobj = {};
	        var thisqs = jQuery.jqURL.url({ win: args.win }).split('?')[1];

	        if (thisqs) {
	            var pairs = thisqs.split('&');
	            for (i = 0; i < pairs.length; i++) {
	                var pair = pairs[i].split('=');
	                qsobj[pair[0]] = pair[1];
	            }
	        }
	        return qsobj;
	    }
	},

    strip:
	function (args) {
	    args = jQuery.extend({
	        keys: '',
	        win: window
	    },
			args);

	    if (jQuery.jqURL.url().indexOf('?') == -1) { // no query string found
	        return jQuery.jqURL.url({ win: args.win });
	    }
	    // if no keys passed in, just return url with no querystring
	    else if (!args.keys) {
	        return jQuery.jqURL.url({ win: args.win }).split('?')[0];
	    }
	    else { //return stripped url

	        var qsobj = jQuery.jqURL.qs({ ret: 'object', win: args.win });  // object with key/value pairs		
	        var counter = 0;
	        var url = jQuery.jqURL.url({ win: args.win }).split('?')[0] + '?';
	        var amp = '';

	        for (var key in qsobj) {
	            if (args.keys.indexOf(key) == -1) {
	                // pass test, add this key/value to string
	                amp = (counter) ? '&' : '';
	                url = url + amp + key + '=' + qsobj[key];
	                counter++;
	            }
	        }
	        return url;
	    }
	},

    get:
	function (key, args) {
	    args = jQuery.extend({
	        win: window
	    }, args);

	    qsobj = jQuery.jqURL.qs({ ret: 'object', win: args.win });
	    return qsobj[key];
	},

    set:
	function (hash, args) {
	    args = jQuery.extend({
	        win: window
	    }, args);

	    // get current querystring
	    var qsobj = jQuery.jqURL.qs({ ret: 'object', win: args.win });

	    // add/set values from hash
	    for (var i in hash) {
	        qsobj[i] = hash[i];
	    }

	    var qstring = '';
	    var counter = 0;
	    var amp = '';

	    // turn qsobj into string
	    for (var k in qsobj) {
	        amp = (counter) ? '&' : '';
	        qstring = qstring + amp + k + '=' + qsobj[k];
	        counter++;
	    }
	    return jQuery.jqURL.strip({ win: args.win }) + '?' + qstring;
	}

};



/*
* Date Format 1.2.3
* (c) 2007-2009 Steven Levithan <stevenlevithan.com>
* MIT license
*
* Includes enhancements by Scott Trenda <scott.trenda.net>
* and Kris Kowal <cixar.com/~kris.kowal/>
*
* Accepts a date, a mask, or a date and a mask.
* Returns a formatted version of the given date.
* The date defaults to the current date/time.
* The mask defaults to dateFormat.masks.default.
*/

var dateFormat = function () {
    var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
		timezoneClip = /[^-+\dA-Z]/g,
		pad = function (val, len) {
		    val = String(val);
		    len = len || 2;
		    while (val.length < len) val = "0" + val;
		    return val;
		};

    // Regexes and supporting functions are cached through closure
    return function (date, mask, utc) {
        var dF = dateFormat;

        // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
        if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
            mask = date;
            date = undefined;
        }

        // Passing date through Date applies Date.parse, if necessary
        date = date ? new Date(date) : new Date;
        if (isNaN(date)) throw SyntaxError("invalid date");

        mask = String(dF.masks[mask] || mask || dF.masks["default"]);

        // Allow setting the utc argument via the mask
        if (mask.slice(0, 4) == "UTC:") {
            mask = mask.slice(4);
            utc = true;
        }

        var _ = utc ? "getUTC" : "get",
			d = date[_ + "Date"](),
			D = date[_ + "Day"](),
			m = date[_ + "Month"](),
			y = date[_ + "FullYear"](),
			H = date[_ + "Hours"](),
			M = date[_ + "Minutes"](),
			s = date[_ + "Seconds"](),
			L = date[_ + "Milliseconds"](),
			o = utc ? 0 : date.getTimezoneOffset(),
			flags = {
			    d: d,
			    dd: pad(d),
			    ddd: dF.i18n.dayNames[D],
			    dddd: dF.i18n.dayNames[D + 7],
			    m: m + 1,
			    mm: pad(m + 1),
			    mmm: dF.i18n.monthNames[m],
			    mmmm: dF.i18n.monthNames[m + 12],
			    yy: String(y).slice(2),
			    yyyy: y,
			    h: H % 12 || 12,
			    hh: pad(H % 12 || 12),
			    H: H,
			    HH: pad(H),
			    M: M,
			    MM: pad(M),
			    s: s,
			    ss: pad(s),
			    l: pad(L, 3),
			    L: pad(L > 99 ? Math.round(L / 10) : L),
			    t: H < 12 ? "a" : "p",
			    tt: H < 12 ? "am" : "pm",
			    T: H < 12 ? "A" : "P",
			    TT: H < 12 ? "AM" : "PM",
			    Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
			    o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
			    S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
			};

        return mask.replace(token, function ($0) {
            return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
        });
    };
} ();

// Some common format strings
dateFormat.masks = {
    "default": "ddd mmm dd yyyy HH:MM:ss",
    shortDate: "m/d/yy",
    mediumDate: "mmm d, yyyy",
    longDate: "mmmm d, yyyy",
    fullDate: "dddd, mmmm d, yyyy",
    shortTime: "h:MM TT",
    mediumTime: "h:MM:ss TT",
    longTime: "h:MM:ss TT Z",
    isoDate: "yyyy-mm-dd",
    isoTime: "HH:MM:ss",
    minute: "yyyy-mm-dd HH:MM",
    isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
    dayNames: [
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
	],
    monthNames: [
		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
	]
};

// For convenience...
Date.prototype.format = function (mask, utc) {
    return dateFormat(this, mask, utc);
};

Date.MillisecondToDate = function (msd) {
    var time = parseFloat(msd) / 1000;
    if (null != time && "" != time) {
        if (time > 60 && time < 60 * 60) {
            time = parseInt(time / 60.0) + "分钟" + parseInt((parseFloat(time / 60.0) -
                parseInt(time / 60.0)) * 60) + "秒";
        }
        else if (time >= 60 * 60 && time < 60 * 60 * 24) {
            time = parseInt(time / 3600.0) + "小时" + parseInt((parseFloat(time / 3600.0) -
                parseInt(time / 3600.0)) * 60) + "分钟" +
                parseInt((parseFloat((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60) -
                parseInt((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60)) * 60) + "秒";
        }
        else {
            time = parseInt(time) + "秒";
        }
    }
    return time;
};

if (!this.JSON) {

    // Create a JSON object only if one does not already exist. We create the
    // object in a closure to avoid global variables.

    JSON = function () {

        function f(n) {    // Format integers to have at least two digits.
            return n < 10 ? '0' + n : n;
        }

        Date.prototype.toJSON = function () {

            // Eventually, this method will be based on the date.toISOString method.

            return this.getUTCFullYear() + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate()) + 'T' +
                 f(this.getUTCHours()) + ':' +
                 f(this.getUTCMinutes()) + ':' +
                 f(this.getUTCSeconds()) + 'Z';
        };


        var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g,
            gap,
            indent,
            meta = {    // table of character substitutions
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                '"': '\\"',
                '\\': '\\\\'
            },
            rep;


        function quote(string) {

            // If the string contains no control characters, no quote characters, and no
            // backslash characters, then we can safely slap some quotes around it.
            // Otherwise we must also replace the offending characters with safe escape
            // sequences.

            return escapeable.test(string) ?
                '"' + string.replace(escapeable, function (a) {
                    var c = meta[a];
                    if (typeof c === 'string') {
                        return c;
                    }
                    c = a.charCodeAt();
                    return '\\u00' + Math.floor(c / 16).toString(16) +
                                               (c % 16).toString(16);
                }) + '"' :
                '"' + string + '"';
        }


        function str(key, holder) {

            // Produce a string from holder[key].

            var i,          // The loop counter.
                k,          // The member key.
                v,          // The member value.
                length,
                mind = gap,
                partial,
                value = holder[key];

            // If the value has a toJSON method, call it to obtain a replacement value.

            if (value && typeof value === 'object' &&
                    typeof value.toJSON === 'function') {
                value = value.toJSON(key);
            }

            // If we were called with a replacer function, then call the replacer to
            // obtain a replacement value.

            if (typeof rep === 'function') {
                value = rep.call(holder, key, value);
            }

            // What happens next depends on the value's type.

            switch (typeof value) {
                case 'string':
                    return quote(value);

                case 'number':

                    // JSON numbers must be finite. Encode non-finite numbers as null.

                    return isFinite(value) ? String(value) : 'null';

                case 'boolean':
                case 'null':

                    // If the value is a boolean or null, convert it to a string. Note:
                    // typeof null does not produce 'null'. The case is included here in
                    // the remote chance that this gets fixed someday.

                    return String(value);

                    // If the type is 'object', we might be dealing with an object or an array or
                    // null.

                case 'object':

                    // Due to a specification blunder in ECMAScript, typeof null is 'object',
                    // so watch out for that case.

                    if (!value) {
                        return 'null';
                    }

                    // Make an array to hold the partial results of stringifying this object value.

                    gap += indent;
                    partial = [];

                    // If the object has a dontEnum length property, we'll treat it as an array.

                    if (typeof value.length === 'number' &&
                        !(value.propertyIsEnumerable('length'))) {

                        // The object is an array. Stringify every element. Use null as a placeholder
                        // for non-JSON values.

                        length = value.length;
                        for (i = 0; i < length; i += 1) {
                            partial[i] = str(i, value) || 'null';
                        }

                        // Join all of the elements together, separated with commas, and wrap them in
                        // brackets.

                        v = partial.length === 0 ? '[]' :
                        gap ? '[\n' + gap + partial.join(',\n' + gap) +
                                  '\n' + mind + ']' :
                              '[' + partial.join(',') + ']';
                        gap = mind;
                        return v;
                    }

                    // If the replacer is an array, use it to select the members to be stringified.

                    if (typeof rep === 'object') {
                        length = rep.length;
                        for (i = 0; i < length; i += 1) {
                            k = rep[i];
                            if (typeof k === 'string') {
                                v = str(k, value, rep);
                                if (v) {
                                    partial.push(quote(k) + (gap ? ': ' : ':') + v);
                                }
                            }
                        }
                    } else {

                        // Otherwise, iterate through all of the keys in the object.

                        for (k in value) {
                            v = str(k, value, rep);
                            if (v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }

                    // Join all of the member texts together, separated with commas,
                    // and wrap them in braces.

                    v = partial.length === 0 ? '{}' :
                    gap ? '{\n' + gap + partial.join(',\n' + gap) +
                              '\n' + mind + '}' :
                          '{' + partial.join(',') + '}';
                    gap = mind;
                    return v;
            }
        }


        // Return the JSON object containing the stringify, parse, and quote methods.

        return {
            stringify: function (value, replacer, space) {

                // The stringify method takes a value and an optional replacer, and an optional
                // space parameter, and returns a JSON text. The replacer can be a function
                // that can replace values, or an array of strings that will select the keys.
                // A default replacer method can be provided. Use of the space parameter can
                // produce text that is more easily readable.

                var i;
                gap = '';
                indent = '';
                if (space) {

                    // If the space parameter is a number, make an indent string containing that
                    // many spaces.

                    if (typeof space === 'number') {
                        for (i = 0; i < space; i += 1) {
                            indent += ' ';
                        }

                        // If the space parameter is a string, it will be used as the indent string.

                    } else if (typeof space === 'string') {
                        indent = space;
                    }
                }

                // If there is no replacer parameter, use the default replacer.

                if (!replacer) {
                    rep = function (key, value) {
                        if (!Object.hasOwnProperty.call(this, key)) {
                            return undefined;
                        }
                        return value;
                    };

                    // The replacer can be a function or an array. Otherwise, throw an error.

                } else if (typeof replacer === 'function' ||
                        (typeof replacer === 'object' &&
                         typeof replacer.length === 'number')) {
                    rep = replacer;
                } else {
                    throw new Error('JSON.stringify');
                }

                // Make a fake root object containing our value under the key of ''.
                // Return the result of stringifying the value.

                return str('', { '': value });
            },


            parse: function (text, reviver) {

                // The parse method takes a text and an optional reviver function, and returns
                // a JavaScript value if the text is a valid JSON text.

                var j;

                function walk(holder, key) {

                    // The walk method is used to recursively walk the resulting structure so
                    // that modifications can be made.

                    var k, v, value = holder[key];
                    if (value && typeof value === 'object') {
                        for (k in value) {
                            if (Object.hasOwnProperty.call(value, k)) {
                                v = walk(value, k);
                                if (v !== undefined) {
                                    value[k] = v;
                                } else {
                                    delete value[k];
                                }
                            }
                        }
                    }
                    return reviver.call(holder, key, value);
                }


                // Parsing happens in three stages. In the first stage, we run the text against
                // regular expressions that look for non-JSON patterns. We are especially
                // concerned with '()' and 'new' because they can cause invocation, and '='
                // because it can cause mutation. But just to be safe, we want to reject all
                // unexpected forms.

                // We split the first stage into 4 regexp operations in order to work around
                // crippling inefficiencies in IE's and Safari's regexp engines. First we
                // replace all backslash pairs with '@' (a non-JSON character). Second, we
                // replace all simple value tokens with ']' characters. Third, we delete all
                // open brackets that follow a colon or comma or that begin the text. Finally,
                // we look to see that the remaining characters are only whitespace or ']' or
                // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

                if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

                    // In the second stage we use the eval function to compile the text into a
                    // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
                    // in JavaScript: it can begin a block or an object literal. We wrap the text
                    // in parens to eliminate the ambiguity.

                    j = eval('(' + text + ')');

                    // In the optional third stage, we recursively walk the new structure, passing
                    // each name/value pair to a reviver function for possible transformation.

                    return typeof reviver === 'function' ?
                        walk({ '': j }, '') : j;
                }

                // If the text is not JSON parseable, then a SyntaxError is thrown.

                throw new SyntaxError('JSON.parse');
            },

            quote: quote
        };
    } ();
}
